home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / od-amiga / ami-rexx.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  17KB  |  537 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * ami-rexx.c
  5.   * 
  6.   * Copyright 1996 Samuel Devulder.
  7.   *
  8.   * History:
  9.   *     05/09/97: Added UAEEXE support.
  10.   */
  11.  
  12. #include <proto/exec.h>
  13. #include <proto/rexxsyslib.h>
  14. #include <proto/dos.h>
  15. #ifndef __SASC
  16. #include <proto/alib.h>
  17. #endif
  18.  
  19. #include <rexx/storage.h>
  20. #include <rexx/errors.h>
  21.  
  22. /* this prevent a conflict between <rexx/rexxio.h> and <sys/dirent.h> */
  23. #undef DT_DIR 
  24.  
  25. /****************************************************************************/
  26.  
  27. #include "sysconfig.h"
  28. #include "sysdeps.h"
  29.  
  30. #include "uae.h"
  31. #include "config.h"
  32. #include "options.h"
  33. #ifdef __GNUC__
  34. #include "../include/memory.h" /* or else gcc includes machdep/memory.h */
  35. #else
  36. #include "/include/memory.h"
  37. #endif
  38. #include "custom.h"
  39. #include "readcpu.h"
  40. #include "newcpu.h"
  41. #include "disk.h"
  42. #include "gui.h"
  43. #include "sound.h"
  44. #include "gensound.h"
  45. #include "uaeexe.h"
  46. #include "threaddep/penguin.h"
  47. #include "xwin.h"
  48.  
  49. #include <ctype.h>
  50.  
  51. /****************************************************************************/
  52.  
  53. #define UAE_PORTNAME    "UAE"
  54. #define RESULT_LEN      1024
  55. #define PORT_LEN        80
  56. #define CMD_LEN         1024
  57.  
  58. typedef struct
  59. {
  60.     char port[PORT_LEN];
  61.     char cmd_on[CMD_LEN];
  62.     char cmd_off[CMD_LEN];
  63. } gui_rexx_s;
  64.  
  65. enum {LED_POW, LED_DF0, LED_DF1, LED_DF2, LED_DF3,
  66.       NAME_DF0, NAME_DF1, NAME_DF2, NAME_DF3,
  67.       ON_EXIT,
  68.       GUI_REXX_MAX};
  69.  
  70. /****************************************************************************/
  71.  
  72. int  rexx_init(void);
  73. void rexx_exit(void);
  74. void rexx_led(int led, int on);
  75. void rexx_filename(int num, char *name);
  76. void rexx_handle_events(void);
  77.  
  78. /****************************************************************************/
  79.  
  80. #ifdef __GNUC__
  81. struct RxsLib
  82. #else
  83. struct Library
  84. #endif
  85.                         *RexxSysBase;
  86. static struct MsgPort   *ARexxPort;
  87. static gui_rexx_s        gui_rexx[GUI_REXX_MAX];
  88. static char              RESULT[RESULT_LEN];
  89. static int               led_state[5];
  90.  
  91. static int   ADDRESS(char *hostname, char *cmd);
  92. static int   matchstr(char **line,char *pat);
  93. static void  extractstr(char **line, char *result, int len);
  94. static int   matchnum(char **line);
  95.  
  96. /****************************************************************************/
  97.  
  98. extern int quit_program;                                 /* ami-gui.c */
  99. extern void activate_debugger(void);                     /* debug.c */
  100. extern char *to_unix_path(char *s);                      /* ami-disk.c */
  101. extern char *from_unix_path(char *s);                    /* ami-disk.c */
  102.  
  103. /****************************************************************************/
  104.  
  105. int rexx_init(void)
  106. {
  107.     quit_program = 0;
  108.     RexxSysBase = (void*)OpenLibrary("rexxsyslib.library",0L);
  109.     if(!RexxSysBase) {
  110.         fprintf(stderr, "Can't find rexxsyslib.library!\n");
  111.         return 1;
  112.     }
  113.     if(FindPort(UAE_PORTNAME)) {
  114.         fprintf(stderr, "Port \"%s\" already exists!\n",UAE_PORTNAME);
  115.         return 1;    
  116.     }
  117.     ARexxPort = CreatePort(UAE_PORTNAME,0);
  118.     if(!ARexxPort) {
  119.         fprintf(stderr, "Failed to open AREXX port \"%s\"!\n",UAE_PORTNAME);
  120.         return 1;
  121.     }
  122.     fprintf(stderr,"Rexx port \"%s\" installed.\n", UAE_PORTNAME);
  123.     rexx_handle_events();
  124.     return 0;
  125. }
  126.  
  127. /****************************************************************************/
  128.  
  129. void rexx_exit(void)
  130. {
  131.     if(ARexxPort) {
  132.         struct RexxMsg *msg;
  133.         gui_rexx_s *gui = &gui_rexx[ON_EXIT];
  134.  
  135.         if(gui->port[0] && gui->cmd_on[0]) {
  136.             if(ADDRESS(gui->port, gui->cmd_on) != RC_OK) {
  137.                 fprintf(stderr,"%s:%s:%s\n", gui->port,
  138.                                              gui->cmd_on,
  139.                                              RESULT);
  140.             }
  141.             gui->port[0] = '\0';
  142.          }
  143.         Forbid();
  144.         while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) {
  145.            msg->rm_Result1 = RC_ERROR;
  146.            msg->rm_Result2 = NULL;
  147.            ReplyMsg((void*)msg);
  148.         }
  149.         DeletePort(ARexxPort);
  150.         Permit();
  151.         ARexxPort = NULL;
  152.     }
  153.     if(RexxSysBase) {
  154.         CloseLibrary((void*)RexxSysBase);
  155.         RexxSysBase = NULL;
  156.     }
  157. }
  158.  
  159. /****************************************************************************/
  160.  
  161. static int EJECT(char *line)
  162. {
  163.     int drive = matchnum(&line);
  164.     if(drive<0 || drive>3) return RC_WARN;
  165.     disk_eject(drive);
  166.     sprintf(RESULT,"Drive %d ejected",drive);
  167.     return RC_OK;
  168. }
  169.  
  170. /****************************************************************************/
  171.  
  172. static int INSERT(char *line)
  173. {
  174.     int drive = matchnum(&line);
  175.     if(drive<0 || drive>3) return RC_WARN;
  176.     if(disk_empty(drive)) {
  177.         char buff[256];
  178.         char *name;
  179.         extractstr(&line, buff, 256);
  180.         name = to_unix_path(buff);
  181.         disk_insert(drive, name);
  182.         free(name);
  183.     } else {
  184.         sprintf(RESULT,"Drive %d not empty!",drive);
  185.         return RC_WARN;
  186.     }
  187.     return RC_OK;
  188. }
  189.  
  190. /****************************************************************************/
  191.  
  192. static void QUIT(void)
  193. {
  194.     broken_in = 1;
  195.     regs.spcflags |= SPCFLAG_BRK;
  196.     quit_program = 1;
  197. }
  198.  
  199. /****************************************************************************/
  200.  
  201. static int QUERY(char *line)
  202. {
  203.     char *res = NULL;
  204.     int   alc = 0;
  205.  
  206.     if     (matchstr(&line, "LED_POW"))  res = led_state[0]?"1":"0";
  207.     else if(matchstr(&line, "LED_DF0"))  res = led_state[1]?"1":"0";
  208.     else if(matchstr(&line, "LED_DF1"))  res = led_state[2]?"1":"0";
  209.     else if(matchstr(&line, "LED_DF2"))  res = led_state[3]?"1":"0";
  210.     else if(matchstr(&line, "LED_DF3"))  res = led_state[4]?"1":"0";
  211.     else if(matchstr(&line, "NAME_DF0")) res = from_unix_path(currprefs.df[0]), alc = 1;
  212.     else if(matchstr(&line, "NAME_DF1")) res = from_unix_path(currprefs.df[1]), alc = 1;
  213.     else if(matchstr(&line, "NAME_DF2")) res = from_unix_path(currprefs.df[2]), alc = 1;
  214.     else if(matchstr(&line, "NAME_DF3")) res = from_unix_path(currprefs.df[3]), alc = 1;
  215.     else if(matchstr(&line, "FAKEJOYSTICK")) res = currprefs.fake_joystick?"1":"0";
  216.     else if(matchstr(&line, "DISPLAY"))  res = inhibit_frame?"0":"1";
  217.     else if(matchstr(&line, "FRAMERATE")) {
  218.         sprintf(RESULT,"%d",currprefs.framerate);
  219.         return RC_OK;
  220.     } else if(matchstr(&line, "SOUND")) {
  221.         sprintf(RESULT,"%d",sound_available?currprefs.produce_sound:-1);
  222.         return RC_OK;
  223.     } 
  224.     else return RC_ERROR;
  225.  
  226.     if(res) {
  227.         strncpy(RESULT, res, RESULT_LEN);
  228.         if(alc) free(res);
  229.     }
  230.     return RC_OK;
  231. }
  232.  
  233. /****************************************************************************/
  234.  
  235. static int FEEDBACK(char *line)
  236. {
  237.     gui_rexx_s *gui = NULL;
  238.  
  239.     if     (matchstr(&line,"LED_POW"))  gui = &gui_rexx[LED_POW];
  240.     else if(matchstr(&line,"LED_DF0"))  gui = &gui_rexx[LED_DF0];
  241.     else if(matchstr(&line,"LED_DF1"))  gui = &gui_rexx[LED_DF1];
  242.     else if(matchstr(&line,"LED_DF2"))  gui = &gui_rexx[LED_DF2];
  243.     else if(matchstr(&line,"LED_DF3"))  gui = &gui_rexx[LED_DF3];
  244.     else if(matchstr(&line,"NAME_DF0")) gui = &gui_rexx[NAME_DF0];
  245.     else if(matchstr(&line,"NAME_DF1")) gui = &gui_rexx[NAME_DF1];
  246.     else if(matchstr(&line,"NAME_DF2")) gui = &gui_rexx[NAME_DF2];
  247.     else if(matchstr(&line,"NAME_DF3")) gui = &gui_rexx[NAME_DF3];
  248.     else if(matchstr(&line,"ON_EXIT"))  gui = &gui_rexx[ON_EXIT];
  249.     else return RC_ERROR;
  250.  
  251.     while(1) {
  252.         if(matchstr(&line, "ADDRESS") ||
  253.            matchstr(&line, "PORT")) {
  254.             extractstr(&line, gui->port, PORT_LEN);
  255.         } else if(matchstr(&line,"COMMAND") ||
  256.                   matchstr(&line,"CMD") ||
  257.                   matchstr(&line,"CMD_ON")) {
  258.             extractstr(&line, gui->cmd_on,  CMD_LEN);
  259.         } else if(matchstr(&line,"CMD_OFF")) {
  260.             extractstr(&line, gui->cmd_off, CMD_LEN);
  261.         } else break;
  262.     }
  263.     return RC_OK;
  264. }
  265.  
  266. /****************************************************************************/
  267.  
  268. static int VERSION(char *line)
  269. {
  270.     if(matchstr(&line,"STRING")) {
  271.         sprintf(RESULT,
  272.                 "UAE-%d.%d.%d © by Bernd Schmidt & contributors, "
  273.                 "Amiga Port by Samuel Devulder.",
  274.                 (version / 100) % 10, (version / 10) % 10, version % 10);
  275.     } else if(matchstr(&line,"NUM")) {
  276.         sprintf(RESULT,"%d",version);
  277.     } else if(matchstr(&line,"AUTHOR")) {
  278.         sprintf(RESULT,"© by Bernd Schmidt & contributors");
  279.     } else if(matchstr(&line,"PORT")) {
  280.         sprintf(RESULT,"Amiga Port by Samuel Devulder");
  281.     } else return RC_ERROR;
  282.     return RC_OK;
  283. }
  284.  
  285. /****************************************************************************/
  286.  
  287. static int FRAMERATE(char *line)
  288. {
  289.     int num;
  290.     num = matchnum(&line);
  291.     if(num>=1 && num<=20) {
  292.         currprefs.framerate = num;
  293.     } else {
  294.         sprintf(RESULT,"Invalid frame rate: %d\n", num);
  295.         return RC_WARN;
  296.     }
  297.     return RC_OK;
  298. }
  299.  
  300. /****************************************************************************/
  301.  
  302. static int FAKEJOYSTICK(char *line)
  303. {
  304.     if     (matchstr(&line,"ON"))     currprefs.fake_joystick = 2;
  305.     else if(matchstr(&line,"OFF"))    currprefs.fake_joystick = 0;
  306.     else if(matchstr(&line,"TOGGLE")) currprefs.fake_joystick =
  307.                                       currprefs.fake_joystick?0:2;
  308.     else return RC_ERROR;
  309.     return RC_OK;
  310. }
  311.  
  312. /****************************************************************************/
  313.  
  314. static int DISPLAY(char *line)
  315. {
  316.     if     (matchstr(&line,"ON"))     inhibit_frame = 0;
  317.     else if(matchstr(&line,"OFF"))    inhibit_frame = 1;
  318.     else if(matchstr(&line,"TOGGLE")) inhibit_frame = inhibit_frame?0:1;
  319.     else return RC_ERROR;
  320.     return RC_OK;
  321. }
  322.  
  323. /****************************************************************************/
  324.  
  325. static int SOUND(char *line)
  326. {
  327.     if(!sound_available) {
  328.         sprintf(RESULT,"Sound not available!");
  329.         return RC_WARN;
  330.     }
  331.  
  332.     if     (matchstr(&line,"ON"))     currprefs.produce_sound = 2;
  333.     else if(matchstr(&line,"OFF"))    currprefs.produce_sound = 1;
  334.     else if(matchstr(&line,"BEST"))   currprefs.produce_sound = 3;
  335.     else if(matchstr(&line,"TOGGLE")) currprefs.produce_sound =
  336.                                       currprefs.produce_sound<=1?2:1;
  337.     else return RC_ERROR;
  338.     return RC_OK;
  339. }
  340.  
  341. /****************************************************************************/
  342.  
  343. static int UAEEXE(char *line)
  344. {
  345.     if(uaeexe(line)) {
  346.         sprintf(RESULT,"Remote CLI failed!");
  347.         return RC_WARN;
  348.     }
  349.     return RC_OK;
  350. }
  351.  
  352. /****************************************************************************/
  353.  
  354. static int process_cmd(char *line)
  355. {
  356.     RESULT[0] = '\0';
  357.     if     (matchstr(&line, "EJECT"))        return EJECT(line);
  358.     else if(matchstr(&line, "INSERT"))       return INSERT(line);
  359.     else if(matchstr(&line, "QUERY"))        return QUERY(line);
  360.     else if(matchstr(&line, "FEEDBACK"))     return FEEDBACK(line);
  361.     else if(matchstr(&line, "VERSION"))      return VERSION(line);
  362.     else if(matchstr(&line, "BYE"))          QUIT();
  363.     else if(matchstr(&line, "QUIT"))         QUIT();
  364.     else if(matchstr(&line, "DEBUG"))        activate_debugger();
  365.     else if(matchstr(&line, "RESET"))        m68k_reset();
  366.     else if(matchstr(&line, "DISPLAY"))      return DISPLAY(line);
  367.     else if(matchstr(&line, "FRAMERATE"))    return FRAMERATE(line);
  368.     else if(matchstr(&line, "FAKEJOYSTICK")) return FAKEJOYSTICK(line);
  369.     else if(matchstr(&line, "SOUND"))        return SOUND(line);
  370.     else if(matchstr(&line, "UAEEXE"))       return UAEEXE(line);
  371.     else return RC_ERROR;
  372.     return RC_OK;
  373. }
  374.  
  375. /****************************************************************************/
  376.  
  377. void rexx_handle_events(void)
  378. {
  379.     struct RexxMsg *msg;
  380.     while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) {
  381.         if(!(msg->rm_Action & RXCOMM)) {
  382.             fprintf(stderr,"Unknown action '%08X' recieved!\n",
  383.                     msg->rm_Action);
  384.             continue;
  385.         }
  386.         msg->rm_Result1 = process_cmd(msg->rm_Args[0]);
  387.         msg->rm_Result2 = NULL;
  388.         if(msg->rm_Action & RXFF_RESULT) {
  389.             msg->rm_Result2 = (LONG)CreateArgstring(RESULT,strlen(RESULT));
  390.         }
  391.         ReplyMsg((void*)msg);
  392.     }
  393. }
  394.  
  395. /****************************************************************************/
  396.  
  397. void rexx_led(int led, int on)
  398. {
  399.     gui_rexx_s *gui = NULL;
  400.  
  401.     if(led < 0 || led > 4) return;
  402.     led_state[led] = on;
  403.  
  404.     if(led == 0) gui = &gui_rexx[LED_POW];
  405.     if(led == 1) gui = &gui_rexx[LED_DF0];
  406.     if(led == 2) gui = &gui_rexx[LED_DF1];
  407.     if(led == 3) gui = &gui_rexx[LED_DF2];
  408.     if(led == 4) gui = &gui_rexx[LED_DF3];
  409.  
  410.     if(gui->port[0] && gui->cmd_on[0] && gui->cmd_off[0]) {
  411.         if(ADDRESS(gui->port, on ? gui->cmd_on : gui->cmd_off) != RC_OK) {
  412.             fprintf(stderr,"%s:%s:%s\n", gui->port,
  413.                                          on ? gui->cmd_on : gui->cmd_off,
  414.                                          RESULT);
  415.         }
  416.     }
  417. }
  418.  
  419. /****************************************************************************/
  420.  
  421. void rexx_filename(int num, char *filename)
  422. {
  423.     gui_rexx_s *gui = NULL;
  424.     if(num < 0 || num > 3) return;
  425.     gui = &gui_rexx[NAME_DF0 + num];
  426.     if(gui->port[0] && gui->cmd_on[0]) {
  427.         char buf[CMD_LEN];
  428.         if(!(filename = from_unix_path(filename))) return;
  429.         sprintf(buf, gui->cmd_on, filename);
  430.         free(filename);
  431.         if(ADDRESS(gui->port, buf) != RC_OK) {
  432.             fprintf(stderr,"%s:%s:%s\n", gui->port, buf, RESULT);
  433.         }
  434.     }
  435. }
  436.  
  437. /****************************************************************************/
  438. /* send a message to an AREXX port.
  439.  */
  440. static int ADDRESS(char *hostname, char *cmd)
  441. {
  442.     struct MsgPort *RexxPort,
  443.                    *ReplyPort;
  444.     struct RexxMsg *HostMsg,
  445.                    *answer;
  446.     int result = RC_WARN;
  447.  
  448.     if(!stricmp(hostname, "COMMAND")) {
  449.         return SystemTagList(cmd,NULL);
  450.     }
  451.  
  452.     if((RexxPort = (void *)FindPort(hostname))) {
  453.         if((ReplyPort = (void *)CreateMsgPort())) {
  454.             if((HostMsg = CreateRexxMsg(ReplyPort, NULL, hostname))) {
  455.                 if((HostMsg->rm_Args[0] = CreateArgstring(cmd,strlen(cmd)))) {
  456.                     HostMsg->rm_Action  = RXCOMM | RXFF_RESULT;
  457.                     PutMsg(RexxPort, (void*)HostMsg);
  458.                     WaitPort(ReplyPort);
  459.                     while(!(answer = (void *)GetMsg(ReplyPort)));
  460.                     result = answer->rm_Result1;
  461.                     if(result == RC_OK) {
  462.                         if(answer->rm_Result2) {
  463.                         strncpy(RESULT,(char *)answer->rm_Result2,RESULT_LEN);
  464.                         DeleteArgstring((char *)answer->rm_Result2);
  465.                         } else RESULT[0] = '\0';
  466.                     }
  467.                     DeleteArgstring(HostMsg->rm_Args[0]);
  468.                 } else strcpy(RESULT, "Can't create argstring!");
  469.                 DeleteRexxMsg(HostMsg);
  470.             } else strcpy(RESULT, "Can't create rexx message!");
  471.             DeleteMsgPort(ReplyPort);
  472.         } else strcpy(RESULT, "Can't alloc reply port!");
  473.     } else sprintf(RESULT, "Port \"%s\" not found!",hostname);
  474.     return result;
  475. }
  476.  
  477. /****************************************************************************/
  478. /* argument parsing routines
  479.  */
  480. static int matchstr(char **line,char *pat)
  481. {
  482.     char *s = *line;
  483.     char match = 0;
  484.     while(isspace(*s)) ++s;
  485.     if(*s=='\"' || *s== '\'') match = *s++;
  486.     while(*s && (tolower(*s)==tolower(*pat)) && (!match || *s!=match)) {++s;++pat;}
  487.     if(match && *s==match && s[1]) ++s;
  488.     if(!*pat && (!*s || isspace(*s))) {
  489.         while(isspace(*s)) ++s;
  490.         *line = s;
  491.         return 1;
  492.     }
  493.     return 0;
  494. }
  495.  
  496. /****************************************************************************/
  497.  
  498. static void extractstr(char **line, char *result, int len)
  499. {
  500.     char *s    = *line;
  501.     char match = 0;
  502.  
  503.     while(isspace(*s)) ++s;
  504.  
  505.     if(*s=='\"' || *s=='\'') match = *s++;
  506.     while(*s && *s != match) {
  507.         if(*s == '\\' && (s[1] == '\'' || s[1] == '\"')) ++s;
  508.         if(len > 1) {*result++ = *s;--len;}
  509.         ++s;
  510.         if(!match && isspace(*s)) break;
  511.     }
  512.     if(match && *s == match) ++s;
  513.     while(isspace(*s)) ++s;
  514.  
  515.     *result  = '\0';
  516.     *line    = s;
  517. }
  518.  
  519. /****************************************************************************/
  520.  
  521. static int matchnum(char **line)
  522. {
  523.     char *s = *line, match = 0;
  524.     int sign = 1, num = 0;
  525.  
  526.     while(isspace(*s)) ++s;
  527.     if(*s=='\"' || *s=='\'') match = *s++;
  528.     if(*s=='-') {sign = -1;++s;}
  529.     if(*s=='+') ++s;
  530.     while(isspace(*s)) ++s;
  531.     while(*s>='0' && *s<='9') num = num*10 + (*s++ - '0');
  532.     if(match && *s==match && s[1]) ++s;
  533.     while(isspace(*s)) ++s;
  534.     *line = s;
  535.     return sign>0?num:-num;
  536. }
  537.